<template>
  <div class="storage-content">
    <div class="storage-num">
      <div id="raid-card" class="raid-num"><span>{{ $t('OTHER_RAID_CARD') }}</span><span>{{ raidNum }}</span></div>
      <div id="volume-card" class="raid-num"><span>{{ $t('HOME_LOGICAL_DISK') }}</span><span>{{ volumeNum }}</span></div>
      <div id="driver-card" class="raid-num"><span>{{ $t('HOME_PHYSICAL_DISK') }}</span><span>{{ driverNum }}</span></div>
    </div>
    <div class="storage-text">
      <div class="storage-tree">
        <el-tree
          ref="treeElementNode"
          v-reqKeepAlive.tree
          :data="storageData.data.foliages"
          :props="treeProps"
          :accordion="false"
          :highlight-current="true"
          :show-checkbox="false"
          :expand-on-click-node="false"
          :node-key="treeProps.labelId"
          :current-node-key="currentNode"
          :default-expanded-keys="expanded.data"
          @node-click="handleNodeClick"
          @node-expand="handleNodeClick"
        >
          <template #default="{ node, data }">
            <el-checkbox
              v-if="data.componentName === 'VolumeNode' && showCheckbox"
              @change="nodeCheck($event).option(data)"
            ></el-checkbox>
            <span :id="data.id" class="custom-tree-node spanLabel" :class="data.className">
              <span class="tree-node-row" :class="{ raidTitle: data.getRaidButton }">
                <span
                  :class="{
                    activeWord: data.active,
                    notActiceWord: !data.active,
                    raidLabel: data.getRaidButton
                  }"
                >
                  <LoadingIcon 
                    v-if="['CreatingNode', 'DeletingNode'].includes(data.componentName)" 
                    class="loading-icon"> </LoadingIcon>
                  <span>{{ node.label }}</span>
                </span>
                <span>
                  <span
                    v-if="data.getRaidButton && data.getRaidButton.isShow && isPrivileges"
                    class="raidBtn"
                  >
                    <template v-for="btn in data.getRaidButton.button" :key="btn.id">
                      <el-button
                        v-if="btn.isShow"
                        :id="btn.id"
                        class="volumn-create-btn"
                        :disabled="btn.disable || systemLocked || onTask || delDisable"
                        :class="{ disabledBtn: btn.disable }"
                        type="text"
                        @click="raidButtonClick(btn.id, data, $event)"
                      >
                        {{ $t(btn.label) }}
                      </el-button>
                    </template>
                  </span>
                  <span class="iconClass">
                    <a
                      v-if="isPrivileges && !systemLocked && !showCheckbox && !delDisable"
                      class="delete_img"
                      @click.stop="deleteOneVolumn(data, $event)"
                    >
                      <img src="/src/assets/common/image/license-delete.png" />
                    </a>
                  </span>
                  <span v-if="data.getCryptoErase && isPrivileges && !systemLocked" class="iconClass">
                    <div class="crypto_img" @click="entryDrive(data, $event)"></div>
                  </span>
                </span>
              </span>
            </span>
          </template>
        </el-tree>
        <div v-if="drawerBox" v-reqKeepAlive.drawer>
          <el-drawer
            ref="drawerRef"
            v-model="drawerBox"
            direction="rtl"
            size="552px"
            :show-close="false"
            class="drawerBox"
            :close-on-click-modal="false"
          >
            <template #title>{{ $t('STORE_ADD_VOLUME') }}</template>
            <div class="drawer-box">
              <DrawerComponent
                :data="storageData"
                :visibility="drawerBox"
                @handle-close="handleClose"
              />
            </div>
          </el-drawer>
        </div>
      </div>
      <div class="storage-info">
        <div class="top-message">
          <CustomAert :title="$t('STORE_TIP', { smsName: smsName })" :content="''" />
        </div>
        <div>
          <component
            :is="component"
            v-if="componentRef"
            ref="raidRef"
            :data="showData"
            :node="clickNode.data"
            :collect-list="collectList"
            :on-task="onTask"
            @change-collect-list="changeCollectList"
          ></component>
        </div>
      </div>
    </div>
  </div>
  <Dialog ref="dialog" :config="diaginfo" @close="dialogCloseFun"></Dialog>
</template>

<script setup lang="ts">
import useStore from '@/stores';
import { ref, reactive, onMounted, computed, shallowRef, provide, watch, nextTick, onUnmounted } from 'vue';
import { ElNotification as elNotification, ElLoading } from 'element-plus';

import { factory, entryDriveFun, deleteBatchVolumnFun, queryTaskProgress, deleteVolumn } from './storage.service';
import { TreeNode } from './models/storage-interface';
import { StorageTree, Raid, RaidNode, RaidEditModel, VolumeNode, VolumeStaticModel } from './models';

import VolumesComponent from './components/volumes/Volumes.vue';
import SpanComponent from './components/span/Span.vue';
import RaidComponent from './components/raid/Raid.vue';
import DriversComponent from './components/drivers/Driver.vue';
import DrawerComponent from './components/volume-create/Drawer.vue';
import CustomAert from '@/components/CustAlert/CustAlert.vue';
import LoadingIcon from '@/components/LoadingIcon/LoadingIcon.vue';
import UploadingIcon from '@/components/UploadingIcon/UploadingIcon.vue';
import { loading, showFailedMessage, showSuccessMessage } from '@/utils/composition';
import { checkPrivil } from '@/apps/app-bmc/router/routes';
import { getErrorTranslate, traduction } from '@/utils/language';
import Dialog from '@/components/Dialog/Dialog.vue';
import { VolumeCreateService } from './components/volume-create/volume-creat.servics';
import { deepClone, showElMessage } from '@/utils/utils';
import { UserPrivil } from '@/model/base-enum';
import $http from '@/utils/http-service';

const store = useStore();
let systemLocked = computed(() => {
  return store.state.glob.systemLocked;
});
const isPrivileges = checkPrivil(UserPrivil.baseConfig);
const storageTree = StorageTree.getInstance();
const componentRef = ref(false);
const treeProps = {
  children: 'children',
  label: 'label',
  labelId: 'labelId',
};
const listPoin = reactive({ data: [] });
const treeElementNode = ref();
let checkedTreeList = {};
const showCheckbox = ref(false);
const expanded: any = reactive({ data: [] });
const currentNode = ref();
const smsName = useStore().state.loct.smsName;
const storageData: any = reactive({
  data: { foliages: [], multipleChange: (node?: TreeNode) => {} },
});
const showData = reactive({ data: [] });
const clickNode = reactive({ data: [] });
const drawerBox = ref(false);
const dataDone = ref(false);
const delDialog = ref(false);
let dialogVisible = ref(false);
const raidRef = ref();
const dynamicComponent = {
  VolumeNode: VolumesComponent,
  SpanNode: SpanComponent,
  RaidNode: RaidComponent,
  DriverNode: DriversComponent,
};
let component = shallowRef();
let componentName = ref('');
const collectList = reactive({});
const trees = reactive({});
const dialog = ref();
type Config = {
  id?: string;
  type?: string;
  title: string;
  content: any;
  param?: any;
};
const diaginfo = reactive({
  id: 'driverCreatMessage',
  type: 'warning',
  title: traduction('COMMON_CONFIRM'),
  content: traduction('COMMON_ASK_OK'),
});
let deleteParam: any;
let entryParam: any;
let creatParam: any;
const volumeCreateService = new VolumeCreateService();
const driverNum = ref(0);
const volumeNum = ref(0);
const raidNum = ref(0);
const batchDeleteData = ref([]);
const batchDeleteSelectedData = ref([]);
const delDisable = ref(false);
const callFactoryFunNumber = ref(0);
const factoryFunPolling = ref<ReturnType<typeof setTimeout> | null>(null);
provide('clickNode', clickNode);
provide('treeRef', treeElementNode);
watch(collectList, newVal => {
  const list = reactive(storageData.data.foliages);
  list.forEach((item: any) => {
    if (collectList[item.id] !== undefined) {
      item.raidButton.button.forEach((ele: any) => {
        ele.disable = collectList[item.id] || false;
      });
    }
  });
});

function doesIdExistInData(data, id) {
  for (const item of data) {
    if (item?.id === id) {
      return true;
    }
    if (item?.children && doesIdExistInData(item?.children, id)) {
      return true;
    }
  }
  return false;
}

function checkIdsInList(data, list) {
  for (const item of list) {
    if (item?.componentName === 'VolumeNode' && doesIdExistInData(data, item.id)) {
      return false;
    }
    if (item?.children && !checkIdsInList(data, item?.children)) {
      return false;
    }
  }
  return true;
}

function factoryFun() {
  loading(true);
  factory()
    .then((storageTreeData: any) => {
      if (storageTreeData) {
        storageData.data = storageTreeData;
        driverNum.value = getNum(storageTreeData.foliages, 'DriverNode');
        volumeNum.value = getNum(storageTreeData.foliages, 'VolumeNode');
        raidNum.value = getNum(storageTreeData.foliages, 'RaidNode');
        showData.data = storageTreeData.getFoliages;
        componentRef.value = true;
        displayComponent(showData.data[0]);
        clickNode.data = showData.data[0];
        listPoin.data = storageTreeData.getFoliages.map((item: any) => {
          return item.id;
        });
      }
      // 限定逻辑盘删除最长时间为1分钟，每2s轮询一次
      if (batchDeleteData.value.length && callFactoryFunNumber.value < 30) {
        if (!checkIdsInList(storageTreeData.foliages, batchDeleteData.value)) {
          showCheckbox.value = false;
          checkedTreeList = {};
          delDisable.value = true;
          storageData.data.foliages[0].children.unshift({
            label: traduction('COMMON_DELETING'),
            componentName: 'DeletingNode',
            disabled: true
          });
          factoryFunPolling.value = setTimeout(() => {
            callFactoryFunNumber.value++;
            factoryFun();
          }, 2000);
          return;
        } else {
          if (batchDeleteSelectedData.value.length === batchDeleteData.value.length) {
            showSuccessMessage();
          }
          if (factoryFunPolling.value) {
            clearTimeout(factoryFunPolling.value);
          }
          factoryFunPolling.value = null;
          showCheckbox.value = false;
          checkedTreeList = {};
          elNotification.closeAll();
          batchDeleteData.value = [];
          callFactoryFunNumber.value = 0;
        }
      } else {
        clearTimeout(factoryFunPolling.value);
        factoryFunPolling.value = null;
        showCheckbox.value = false;
        checkedTreeList = {};
        elNotification.closeAll();
        batchDeleteData.value = [];
        callFactoryFunNumber.value = 0;
      }
      dataDone.value = true;
      delDisable.value = false;
      loading(false);
      let createTask = JSON.parse(localStorage.getItem('createTask') || '{}');
      if (localStorage.getItem('createTask') && !onTask.value && createTask?.url) {
        storageData.data.foliages?.forEach((r: any) => {
          if (r.id === createTask?.raidId) {
            r.children.unshift({
              label: traduction('COMMON_CREATING'),
              componentName: 'CreatingNode',
              disabled: true,
            });
          }
        });
        taskRunning(createTask?.url);
      } else {
        localStorage.removeItem('createTask');
      }
    })
    .catch((error: any) => {
      loading(false);
      delDisable.value = false;
    })
    .finally(() => {
      currentNode.value = storageData?.data?.foliages?.length 
        ? storageData?.data?.foliages[0][treeProps.labelId] 
        : '';
    });
}
function changeCollectList(id: string, value: boolean) {  
  collectList[id] = value;
}
onMounted(() => {
  factoryFun();
  const list = storageTree.getFoliages;
  list.forEach((item: any) => {
    if (collectList[item.id] !== undefined) {
      item.raidButton.button.forEach((ele: any) => {
        ele.disable = collectList[item.id] || false;
      });
    }
  });
});

function getNum(data: any, type: string, diskSet: any = new Set()): any {
  for (let item of data) {
    if (item?.children?.length > 0) {
      getNum(item.children, type, diskSet);
    }
    if (item.componentName === type) {
      diskSet.add(item.id);
    }
  }
  return diskSet.size;
}

function handleNodeClick(data: any, properties?: any) {
  treeElementNode.value.setCurrentKey(data.labelId);
  componentRef.value = false;
  clickNode.data = data;
  provide('clickNode', clickNode);
  displayComponent(data);
  $http.keepAlive('Activate');
}

function raidButtonClick(id: string, node: RaidNode, event?: any): void {
  event.stopPropagation();
  switch (id) {
    case 'add':
      addVolume(node);
      break;
    case 'edit':
      editRaid(node);
      break;
    case 'delete':
      deleteBatchVolumn();
      break;
    case 'cancel':
      cancelEdit(node);
      break;
    default:
      break;
  }
}
function addVolume(node: any) {
  // 选中节点
  handleNodeClick(node);
  drawerBox.value = true;
}
function editRaid(node: RaidNode) {
  storageData.data.multipleChange(node);
  node.expanded = true;
  node.setAddButShow = false;
  node.setEditButShow = false;
  node.setCancleButShow = true;
  node.setDelButShow = true;
  showCheckbox.value = true;
  expanded.data = [node.labelId];
}
function deleteBatchVolumn() {
  diaginfo.id = 'deleteBatchVolumnMessage';
  diaginfo.title = traduction('COMMON_CONFIRM');
  diaginfo.content = traduction('STORE_CONFIRM_CONTINUE');
  dialog.value.show();
}
function cancelEdit(node: RaidNode) {
  node.setMultiple = false;
  node.setAddButShow = true;
  node.setEditButShow = true;
  node.setCancleButShow = false;
  node.setDelButShow = false;
  showCheckbox.value = false;
  checkedTreeList = {};
}
function displayComponent(node: TreeNode, isEdit?: any) {
  // 选中节点
  StorageTree.getInstance().checkedNode(node.labelId, node.getRaidIndex);
  componentName.value = node.componentName;
  component.value = dynamicComponent[componentName.value];
  componentRef.value = true;
  if (!isEdit) {
    nextTick(() => {
      if (Object.prototype.hasOwnProperty.call(raidRef.value, 'checkNode')) {
        raidRef.value.checkNode(node);
      } else {
        raidRef.value?.factoryFun(node);
      }
    });
  }
  // 如果加载的是控制器组件，则每次切换时都改变PMC卡的关联逻辑盘列表数据
  if (node.label && VolumeStaticModel.logicDriverList[node.label]) {
    VolumeStaticModel.logicDriverList.maxCacheCount = VolumeStaticModel.logicDriverList[node.label].maxCacheCount;
  } 
}

function deleteOneVolumn(node: VolumeNode, event?: any) {
  diaginfo.id = 'deleteOneVolumeMessage';
  diaginfo.title = traduction('COMMON_CONFIRM');
  diaginfo.content = traduction('STORE_CONFIRM_CONTINUE');
  deleteParam = node;
  dialog.value.show();
}
function entryDrive(node: VolumeNode, event?: any) {
  diaginfo.id = 'entryDriveMessage';
  diaginfo.title = traduction('COMMON_CONFIRM');
  diaginfo.content = traduction('STORE_CONFIRM_CONTINUE');
  entryParam = node;
  dialog.value.show();
}
function handleClose(val: boolean, param?: any) {
  creatParam = param;
  diaginfo.id = val ? 'creatOK' : 'creatCancel';
  diaginfo.title = traduction('COMMON_CONFIRM');
  diaginfo.content = traduction('COMMON_ASK_OK');
  dialog.value.show();
}
function dialogCloseFun(val: boolean) {
  if (val) {
    if (diaginfo.id === 'driverCreatMessage') {
      driverCreat();
      drawerBox.value = false;
    } else if (diaginfo.id === 'entryDriveMessage') {
      entryDriveFun(entryParam)
        .then(() => {
          showSuccessMessage();
        })
        .catch(() => {
          showFailedMessage();
        });
    } else if (diaginfo.id === 'deleteOneVolumeMessage') {
      const selectedData = [deleteParam];
      deleteVolumnFun(selectedData);
    } else if (diaginfo.id === 'creatOK') {
      driverCreat();
      drawerBox.value = false;
    } else if (diaginfo.id === 'deleteBatchVolumnMessage') {
      const list = Object.values(checkedTreeList);
      if (list.length > 0) {
        deleteVolumnFun(list);
      }
    } else {
      dialog.value.hide();
      drawerBox.value = false;
    }
  } else {
    if (diaginfo.id === 'creatCancel') {
      dialog.value.hide();
      return;
    }
  }
  dialog.value.hide();
  drawerBox.value = false;
}
function driverCreat() {
  loading(true);
  volumeCreateService
    .createVolumn()
    .then((res) => {
      loading(false);
      const raidNode = StorageTree.getInstance().getCheckedNode as RaidNode;
      if (res.data.url) {
        storageData.data.foliages[0].children.unshift({
          label: traduction('COMMON_CREATING'),
          componentName: 'CreatingNode',
          disabled: true,
        });
        localStorage.setItem('createTask', JSON.stringify({
          url: res.data.url,
          raidId: raidNode.id,
        }));
      }
      queryTask(res.data.url);
    })
    .catch(error => {
      loading(false);
      const errorCode = error.data.error[0].code;
      showFailedMessage(getErrorTranslate(errorCode));
    });
}
function nodeCheck(val: boolean) {
  const option = (data: any) => {
    if (val) {
      if (!checkedTreeList[data.labelId]) {
        checkedTreeList[data.labelId] = data;
      }
    } else {
      delete checkedTreeList[data.labelId];
    }
  };
  return { option };
}
function handleDeleteVolumn(nodeId, raidId) {
  return new Promise((resolve, reject) => {
    deleteVolumn(nodeId, raidId)
      .then(res => {
        resolve(res);
      })
      .catch(err => {
        reject(err);
      });
  });
}

async function handleBatchDeleteVolumn(selectedData) {
  batchDeleteSelectedData.value = selectedData;
  const delErrorData = [];
  for (let i = 0; i < selectedData.length; i++) {
    const node = selectedData[i];
    const volumeNode = node;
    const raid = StorageTree.getInstance().getParentRaid(volumeNode.getRaidIndex);
    try {
      const result = await handleDeleteVolumn(node.id, raid.id);
      batchDeleteData.value.push(selectedData[i]);
    } catch (error) {
      delErrorData.push(selectedData[i]);
    }
  }
  if (delErrorData.length) {
    showFailedMessage();
    loading(false);
    elNotification.closeAll();
  }
  factoryFun();
}

function deleteVolumnFun(selectedData: any) {
  elNotification({
    title: traduction('COMMON_DELETING'),
    message: traduction('STORE_DELETE_VOLUME_TIPS'),
    icon: UploadingIcon as any,
    position: 'bottom-right',
    duration: 0,
    offset: 10,
  });
  storageData.data.foliages[0].children.unshift({
    label: traduction('COMMON_DELETING'),
    componentName: 'DeletingNode',
    disabled: true,
  });
  loading(true);
  handleBatchDeleteVolumn(selectedData);
}

const progress = ref(0);
const onTask = ref(false);
let taskStateErrorAmount = 0;
// 任务进度查询
let taskInterval: any = null;
// 逻辑盘创建任务进度
function queryTask(url: string) {
  queryTaskProgress(url).then(
    res => {
      const taskData = res.data;
      getInitProgress(url, taskData);
    },
  ).catch((err) => {
    executeUpgradeFailed(err?.data.error[0].code);
  });
}
function getInitProgress(url: string, taskData: any): void {
  if (taskData.state === 'Completed' && taskData.prepare_progress === 100) {
    taskCompleted(taskData);
    localStorage.removeItem('createTask');
  } else if (taskData.state === 'Running' || taskData.state === 'Starting' || taskData.state === 'New') {
    taskRunning(url);
  } else if (taskData.state === 'Exception') {
    exceptionHandler(taskData);
    localStorage.removeItem('createTask');
  } else {
    taskOtherCases(taskData, url);
  }
}
/**
 * 重新触发进度查询
 * 查询间隔设置为2秒
 */
function reQueryProgress(url: string) {
  taskInterval = window.setTimeout(() => {
    queryTask(url);
  }, 2000);
}
// 清除定时查询任务
function clearQueryProgress() {
  if (taskInterval) {
    clearTimeout(taskInterval);
    taskInterval = null;
  }
}
// 升级失败状态码处理
function executeUpgradeFailed(messageId: string) {
  onTask.value = false;
  let msg = traduction('COMMON_FAILED');
  if (messageId) {
    msg = getErrorTranslate(messageId);
  }
  factoryFun();
  displayUpgradeState('failed', msg);
  localStorage.removeItem('createTask');
}

// 任务进行状态提示
function displayUpgradeState(state: 'success' | 'failed' | 'clear', msg: string) {
  elNotification.closeAll();
  if (state === 'failed') {
    showElMessage('error', msg);
  } else if (state === 'success') {
    showSuccessMessage();
  } else {
  }
}

// 进度查询时，其他state状态处理
function taskOtherCases(taskData: any, url: string) {
  taskStateErrorAmount++;
  // 出现状态不对时, 重试次数为10次
  if (taskStateErrorAmount > 10) {
    // 执行任务失败流程
    executeUpgradeFailed(taskData.message_id);
    return;
  }
  reQueryProgress(url);
}
// 任务完成后处理逻辑
function taskCompleted(taskData: any) {
  clearQueryProgress();
  progress.value = 100;
  showSuccessMessage();
  localStorage.removeItem('createTask');
  factoryFun();
  onTask.value = false;
  elNotification.closeAll();
}
// 任务轮询的处理逻辑
function taskRunning(url: string) {
  if (!onTask.value) {
    elNotification({
      title: traduction('COMMON_CREATING'),
      message: traduction('STORE_ADD_VOLUME_TIPS'),
      icon: UploadingIcon as any,
      position: 'bottom-right',
      duration: 0,
      offset: 10,
    });
  } 
  onTask.value = true;
  reQueryProgress(url);
}
// 任务状态异常处理(表示任务失败)
function exceptionHandler(taskData: any) {
  onTask.value = false;
  executeUpgradeFailed(taskData.message_id);
}

onUnmounted(() => {
  clearQueryProgress();
  clearTimeout(factoryFunPolling.value);
  factoryFunPolling.value = null;
  elNotification.closeAll();
});
</script>

<style lang="scss" scoped>
#storageTitle {
  height: auto;
  font-size: 18px;
  color: var(--o-text-color-primary);
  line-height: 24px;
  margin-top: 16px;
  font-weight: bolder;
}
.storage-content {
  height: 100%;
  padding-bottom: 24px;
  flex-direction: row !important;
  .storage-text {
    display: flex;
    justify-content: space-between;
    height: calc(100% - 72px);
    flex-direction: row !important;
  }
  .storage-num {
    display: flex;
    justify-content: space-between;
    padding-right: 24px;
    .raid-num {
      display: flex;
      justify-content: space-between;
      align-items: center;
      height: 56px;
      width: 33%;
      font-size:14px;
      color:#000000;
      font-weight:regular;
      line-height:22px;
      border-radius:4px;
      background:#FFFFFF;
      border:1px soild #E6EBF5;
      padding: 17px 24px;
      margin-bottom: 16px;
    }
  }
}

.storage-tree {
  background-color: var(--o-bg-color-base);
  width: 332px;
  border-radius: 4px;
  margin-right: 8px;
  height: 100%;
  padding: 16px 8px;
  max-height: calc(100vh - 159px);
  overflow: scroll;
  .drivers-num {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
    margin-left: 8px;
    .left-text{
      font-size:16px;
      color:#000000;
      font-weight:medium;
    }
    .label-content {
      background: var(--o-border-color-light);
      border-radius: 8px;
      width: 28px;
      height: 16px;
      display: inline-block;
      text-align: center;
      margin: 0 0px 0 8px;
      font-size: 12px;
      font-weight: 900;
    }

    .label {
      font-size: 12px;
      color: $APP-COLOR-TEXT;
      letter-spacing: 0;
      line-height: 16px;
    }
  }
  .spanLabel {
    flex-shrink: 1;
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .custom-tree-node {
    padding-right: 16px;
    position: relative;
  }
  :deep(.el-tree-node.is-current > .el-tree-node__content .el-tree-node__expand-icon:not(.is-leaf)) {
    color: #fff;
  }
  .raidTitle {
    width: 100%;
    display: flex;
    justify-content: space-between;
  }
  .el-button--text {
    border: none;
    min-width: auto;
    color: var(--o-color-primary);
  }
  :deep(.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content) {
    background-color: var(--o-color-primary);
    border-radius: 4px;
    color: #fff;
    .el-button--text > span {
      color: #fff;
    }
  }
  .delete_img {
    height: 16px;
    width: 16px;
    cursor: pointer;
    display: none;
    overflow: hidden;
    img {
      margin-right: 8px;
      position: relative;
    }
  }

  .el-tree-node__label .el-checkbox {
    margin-right: 8px;
  }

  .el-tree-node__content:hover {
    .volumeClass .delete_img {
      display: block;
      img {
        left: -20px;
        filter: drop-shadow(20px 0 0 var(--o-color-danger));
      }
    }
  }
}
.storage-info {
  flex: 1;
  padding-right: 24px;
}
:deep(.el-drawer__header) {
  font-size: 16px;
  font-weight: bold;
}
:deep(.el-drawer.rtl) {
  height: calc(100% - 48px);
  top: auto;
}
.volumn-create-btn {
  font-weight: bolder;
}
.drawer-box {
  height: 100%;
}
:deep(.el-drawer__body) {
  padding-bottom: 8px;
  padding-top: 16px;
  padding-left: 24px;
}
:deep(.el-drawer__header) {
  color: var(--o-text-color-primary);
  margin-bottom: 0;
}
:deep(.el-button) {
  &:not(.el-dropdown__caret-button) > span {
    min-width: 0;
  }
}
.storage-content {
  :deep(.el-overlay) {
    .el-drawer__body {
      padding: 0;
    }
  }
}
:deep(.top-message) {
  .bc-title {
    font-weight: 100;
  }
}
:deep(.storage-tree) {
  .spanLabel {
    &:hover {
      color: var(--o-button-color_hover);
    }
  }
}
.tree-node-row {
  display: flex;
  flex: 1;
  justify-content: space-between;
}
.loading-icon {
  margin-right: 8px;
  position: absolute;
  width: 16px;
  height: 16px;
  top: 0;
  left: -20px;
}
</style>
